import axios, {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  AxiosError,
  AxiosPromise
} from "axios";
import config from "@/config";

enum Method {
  GET = "GET",
  POST = "POST",
  PUT = "PUT",
  DELETE = "DELETE"
}

class HttpRequest {
  private _baseURL: string;
  private _timeout = 3000;
  constructor() {
    this._baseURL = config.baseURL;
  }
  _setInterceptors(instance: AxiosInstance) {
    instance.interceptors.request.use((config) => config);
    instance.interceptors.response.use(
      ({ status, data }: AxiosResponse) => {
        if (status === 200 && data.err === 0) {
          return Promise.resolve(data);
        }
        return Promise.reject(data.data);
      },
      (err: AxiosError) => {
        this._errorController(err);
        return Promise.reject(err);
      }
    );
  }

  _errorController(err: AxiosError) {
    const { response } = err;
    switch (response?.status) {
      case 401:
        console.log(err);
        break;
      default:
        break;
    }
  }
  _mergeOptions(options: AxiosRequestConfig) {
    return {
      baseURL: this._baseURL,
      timeout: this._timeout,
      ...options
    };
  }
  request(options: AxiosRequestConfig): AxiosPromise {
    const instance = axios.create();
    this._setInterceptors(instance);
    return instance(this._mergeOptions(options));
  }

  get(
    url: string,
    config?: AxiosRequestConfig
  ): AxiosPromise {
    return this.request({
      method: Method.GET,
      url,
      ...config
    });
  }
  delete(url: string, config?: AxiosRequestConfig): AxiosPromise {
    return this.request({
      method: Method.DELETE,
      url,
      ...config
    });
  }
  post(
    url: string,
    data: Record<string, string | number | boolean>,
    config?: AxiosRequestConfig
  ): AxiosPromise {
    return this.request({
      method: Method.POST,
      url,
      data,
      ...config
    });
  }
  put(
    url: string,
    data: Record<string, string | number | boolean>,
    config?: AxiosRequestConfig
  ): AxiosPromise {
    return this.request({
      method: Method.PUT,
      url,
      data,
      ...config
    });
  }
}
export default new HttpRequest();
